/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mballem.app.frame;

import com.mballem.app.bean.ChatMessage;
import com.mballem.app.bean.ChatMessage.Action;
import com.mballem.app.service.ClienteService;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;

/**
 *
 * @author Andre
 */
public class ClienteFrame extends javax.swing.JFrame {
    
    private Socket socket;
    private ChatMessage message;
    private ClienteService service;

    /**
     * Creates new form ClienteFrame
     */
    public ClienteFrame() {
        initComponents();
    }
    
    private class ListenerSocket implements Runnable {
        
        private ObjectInput input;
        
        public ListenerSocket(Socket socket) {
            try {
                this.input = new ObjectInputStream(socket.getInputStream());
            } catch (IOException ex) {
                Logger.getLogger(ClienteFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        @Override
        public void run() {
            try {
                ChatMessage message = null;
                
                while ((message = (ChatMessage) input.readObject()) != null) {
                    ChatMessage.Action action = message.getAction();
                    
                    if (action.equals(ChatMessage.Action.CONNECT)) {
                        
                        connected(message);
                        
                    } else if (action.equals(ChatMessage.Action.DESCONNECT)) {
                        
                        disconnected();
                        socket.close();
                        
                    } else if (action.equals(ChatMessage.Action.SEND_ONE)) {
                        
                        receive(message);
                        
                    } else if (action.equals(ChatMessage.Action.USERS_ONLINE)) {
                        
                        refreshOnlines(message);
                        
                    }
                }
            } catch (ClassNotFoundException | IOException ex) {
                Logger.getLogger(ClienteFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    private void connected(ChatMessage message) {
        if (message.getText().equals("NO")) {
            this.jTF_name.setText("");
            JOptionPane.showMessageDialog(this, "Conexão não realizada!\nTente novamente com um novo nome.");
            return;
        }
        
        this.message = message;
        this.jB_conectar.setEnabled(false);
        this.jTF_name.setEditable(false);
        
        this.jB_sair.setEnabled(true);
        this.jTA_send.setEnabled(true);
        this.jTA_Receive.setEnabled(true);
        this.jB_enviar.setEnabled(true);
        this.jB_limpar.setEnabled(true);
        
        JOptionPane.showMessageDialog(this, "Você esta conectado no chat!");
    }
    
    private void disconnected() {
        
        this.jB_conectar.setEnabled(true);
        this.jTF_name.setEditable(true);
        
        this.jB_sair.setEnabled(false);
        this.jTA_send.setEnabled(false);
        this.jTA_Receive.setEnabled(false);
        this.jB_enviar.setEnabled(false);
        this.jB_limpar.setEnabled(false);
        
        this.jTA_Receive.setText("");
        this.jTA_send.setText("");
        JOptionPane.showMessageDialog(this, "Você saiu do chat!");
        
    }
    
    private void receive(ChatMessage message) {
        this.jTA_Receive.append(message.getName() + " diz: " + message.getText() + "\n");
        
    }
    
    private void refreshOnlines(ChatMessage message) {
        Set<String> names = message.getSetOnlines();
        
        String[] array = (String[]) names.toArray(new String[names.size()]);
        
        names.remove(message.getName());
        this.listOnlines.setListData(array);
        this.listOnlines.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.listOnlines.setLayoutOrientation(JList.VERTICAL);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jTF_name = new javax.swing.JTextField();
        jB_conectar = new javax.swing.JButton();
        jB_sair = new javax.swing.JButton();
        jPanel2 = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        listOnlines = new javax.swing.JList();
        jPanel3 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTA_Receive = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTA_send = new javax.swing.JTextArea();
        jB_enviar = new javax.swing.JButton();
        jB_limpar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Conectar"));

        jB_conectar.setText("Conectar");
        jB_conectar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jB_conectarActionPerformed(evt);
            }
        });

        jB_sair.setText("Sair");
        jB_sair.setEnabled(false);
        jB_sair.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jB_sairActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jTF_name, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jB_conectar)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jB_sair)
                .addContainerGap(18, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jTF_name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jB_conectar)
                .addComponent(jB_sair))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Onlines"));

        jScrollPane3.setViewportView(listOnlines);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 82, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addComponent(jScrollPane3)
                .addContainerGap())
        );

        jPanel3.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jTA_Receive.setColumns(20);
        jTA_Receive.setEditable(false);
        jTA_Receive.setRows(5);
        jTA_Receive.setEnabled(false);
        jScrollPane1.setViewportView(jTA_Receive);

        jTA_send.setColumns(20);
        jTA_send.setRows(5);
        jTA_send.setEnabled(false);
        jScrollPane2.setViewportView(jTA_send);

        jB_enviar.setText("Enviar");
        jB_enviar.setEnabled(false);
        jB_enviar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jB_enviarActionPerformed(evt);
            }
        });

        jB_limpar.setText("Limpar");
        jB_limpar.setEnabled(false);
        jB_limpar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jB_limparActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addComponent(jScrollPane2)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(jB_limpar)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jB_enviar)))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 141, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 76, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jB_limpar)
                    .addComponent(jB_enviar))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(30, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jB_conectarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jB_conectarActionPerformed
        
        String name = jTF_name.getText();
        
        if (!name.isEmpty()) {
            this.message = new ChatMessage();
            this.message.setAction(Action.CONNECT);
            this.message.setName(name);
            
            this.service = new ClienteService();
            this.socket = this.service.connect();
            
            new Thread(new ListenerSocket(this.socket)).start();
            
            this.service.send(message);
        }
    }//GEN-LAST:event_jB_conectarActionPerformed
    
    private void jB_sairActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jB_sairActionPerformed
        this.message.setAction(Action.DESCONNECT);
        this.service.send(this.message);
        disconnected();
    }//GEN-LAST:event_jB_sairActionPerformed
    
    private void jB_enviarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jB_enviarActionPerformed
        String text = this.jTA_send.getText();
        String name = this.message.getName();
        
        this.message = new ChatMessage();
        
        if (this.listOnlines.getSelectedIndex() > -1){
            this.message.setNameReserved((String) this.listOnlines.getSelectedValue());
            this.message.setAction(Action.SEND_ONE);
            this.listOnlines.clearSelection();
        } else {
            this.message.setAction(Action.SEND_ALL);
        }
        if (!text.isEmpty()) {
            this.message = new ChatMessage();
            this.message.setName(name);
            this.message.setText(text);
            
            this.jTA_Receive.append("Você disse: " + text + "\n");
            this.service.send(this.message);
        }
        
        jTA_send.setText("");
    }//GEN-LAST:event_jB_enviarActionPerformed

    private void jB_limparActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jB_limparActionPerformed
        jTA_send.setText("");
    }//GEN-LAST:event_jB_limparActionPerformed
    /**
     * @param args the command line arguments
     */
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jB_conectar;
    private javax.swing.JButton jB_enviar;
    private javax.swing.JButton jB_limpar;
    private javax.swing.JButton jB_sair;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextArea jTA_Receive;
    private javax.swing.JTextArea jTA_send;
    private javax.swing.JTextField jTF_name;
    private javax.swing.JList listOnlines;
    // End of variables declaration//GEN-END:variables
}
